<?php
declare (strict_types=1);

namespace app\common\service;

use app\common\model\AdminMenuModel;
use app\common\model\AdminRoleAuthModel;
use app\common\model\AdminRoleModel;
use think\facade\Cache;

class AdminMenuService
{

    public static $ins = false;
    protected $cache_time = 0;

    private function __construct()
    {
    }

    public static function ins(): self
    {
        if (self::$ins === false) {
            self::$ins = new self();
        }
        return self::$ins;
    }

    /*
     * @title 获取角色缓存的key
     * @param int $id 唯一id
     * @return string
     * */
    public function getCacheKey(int $id): string
    {
        return config('app.menu_key') . $id;
    }

    /*
     * @title 获取角色是否有url权限
     * @param int $role_id 角色的id
     * @param string $url 访问的url地址
     * @return bool
     * */
    public function checkAdminAuth(int $role_id, string $url): bool
    {
        if ($role_id == config('app.super_role_id')) {
            return true;
        }
        $data = $this->getUserMenuAuth($role_id);
        if (!$data) {
            return false;
        }
        if (isset($data[$url])) {
            return true;
        }
        return false;
    }

    /*
     * @title 获取角色菜单和权限,按照父子菜单层级显示
     * @param int $role_id 角色的id
     * @return array
     * */
    public function getRoleMenu(int $role_id): array
    {
        $cache_key = $this->getCacheKey($role_id);

        $data = Cache::store('redis')->get($cache_key);

        if ($data) return $data;
        $AdminMenuModel = new AdminMenuModel();
        $list = $AdminMenuModel->getMenu();

        if ($role_id == config('app.super_role_id')) {
            Cache::store('redis')->set($cache_key, $list, $this->cache_time);
            return $list;
        } else {
            $allowList = [];
            $data = AdminRoleAuthModel::where('role_id', $role_id)->column('menu_id');
            foreach ($list as $key => $item) {
                if (!in_array($item['id'], $data)) {
                    unset($list[$key]);
                    continue;
                }
                if ($item['url']) {
                    $allowList[$item['url']] = 1;
                }
                foreach ($list[$key]['children'] as $kk => $vv) {
                    if (!in_array($vv['id'], $data)) {
                        unset($list[$key]['children'][$kk]);
                        continue;
                    }
                    if ($vv['url']) {
                        $allowList[$vv['url']] = 1;
                    }
                    foreach ($list[$key]['children'][$kk]['children'] as $k => $v) {
                        if (!in_array($v['id'], $data)) {
                            unset($list[$key]['children'][$kk]['children'][$k]);
                            continue;
                        }
                        if ($v['url']) {
                            $allowList[$v['url']] = 1;
                        }
                    }
                }
            }
            $this->setUserMenuAuth($role_id, $allowList);
            $data = array_values($list);
            Cache::store('redis')->set($cache_key, $data, $this->cache_time);
            return $data;
        }
    }

    /*
     * @title 获取全部菜单，不按照层级显示
     * @param int $type 类型
     * @return array
     * */
    public function _getAllMenu(int $type = 0): array
    {
        $AdminMenuModel = new AdminMenuModel();
        $list = $AdminMenuModel->getMenuLev();
        switch ($type) {
            case 1:
                foreach ($list as $k => $v) {
                    if ($v['url'] != '') {
                        unset($list[$k]);
                    }
                }
                $list = array_values($list);
                break;
            default:
        }
        return $list;
    }

    /*
     * @title 清除所有角色的缓存
     * @return bool
     * */
    public function clearCache(): bool
    {
        //清除角色的菜单缓存
        $list = AdminRoleModel::select();
        foreach ($list as $value) {
            $cache_key = $this->getCacheKey($value->getAttr('role_id'));
            Cache::store('redis')->delete($cache_key);
        }
        //清除全部菜单的缓存
        $pid_list = AdminMenuModel::where('url', '')->field('id,pid')->select();
        Cache::store('redis')->delete(config('app.menu_hash_table') . '0');
        foreach ($pid_list as $val) {
            Cache::store('redis')->delete(config('app.menu_hash_table') . (string)$val->getAttr('id'));
        }
        Cache::store('redis')->delete(config('app.all_menu_key'));
        return true;
    }

    /*
     * @title 设置角色的权限
     * @param int $role_id 角色id
     * @param array $data 权限信息
     * @return bool
     * */
    public function setUserMenuAuth(int $role_id, array $data): bool
    {
        return Cache::store('redis')->set(config('app.menu_auth_cache_key') . $role_id, $data, 0);
    }

    /*
     * @title 获取角色的权限
     * @param int $role_id 角色id
     * @return array
     * */
    public function getUserMenuAuth(int $role_id): array
    {
        $info = Cache::store('redis')->get(config('app.menu_auth_cache_key') . $role_id);
        if (empty($info)) {
            return [];
        }
        return $info;
    }

    /*
     * @title 获取菜单的名称
     * @param string url 访问的url地址
     * @return array
     * */
    public function getMenuName(string $url): array
    {
        $menu_name = ['未知', '未知', '未知'];
        if (!isset($url) || $url == '') {
            return $menu_name;
        }

        $url_info = Cache::store('redis')->get(config('app.menu_url_info') . $url);
        if (!$url_info) {
            return $menu_name;
        }
        $menu_name['id'] = $url_info['id'];
        $menu_name[2] = $url_info['name'];

        $url_info = Cache::store('redis')->get(config('app.menu_id_info') . $url_info['pid']);
        if (!$url_info) {
            $menu_name['id'] = $url_info['id'];
            return $menu_name;
        }
        $menu_name[1] = $url_info['name'];
        $url_info = Cache::store('redis')->get(config('app.menu_id_info') . $url_info['pid']);
        if (!$url_info) {
            return $menu_name;
        }
        $menu_name[0] = $url_info['name'];
        return $menu_name;
    }

}